package com.smasher.weight.base

import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Handler
import android.os.IBinder
import android.os.Message
import android.os.RemoteException
import android.text.TextUtils
import android.util.Log
import com.smasher.core.other.WeakReferenceHandler
import com.smasher.weight.R
import com.smasher.weight.entity.WeightEntity
import com.smasher.weight.helper.PackageHelper
import com.tbossgroup.tbscale.EventBatteryPower
import com.tbossgroup.tbscale.TBScaleAidlInterface

/**
 * entry
 *
 * @author smasher
 */
abstract class WeightActivity : BaseLoongActivity() {

    private val weightMessageCallback = Handler.Callback { msg ->
        val what = msg.what
        return@Callback when (what) {
            WHAT_REFRESH_UI -> {
                refreshWeightRecord()
                true
            }

            WHAT_REBIND_SERVICE -> {
                bindService()
                true
            }

            WHAT_TBS_CONNECTED -> {
                if (checkWeightLegal()) {
                    Log.e(TAG, "onRecheckTbs: ")
                    onWeightError()
                } else {
                    loongSendMessage(buildMessage(getString(R.string.weight_action_connected)))
                    handleWeightConnected()
                }
                true
            }

            WHAT_TBS_UNCONNECTED -> {
                handleWeightDisconnected()
                true
            }

            WHAT_TOAST -> {
                val message = msg.obj
                if (message is String) {
                    if (launcherDelay) {
                        handleMessageImmediate(message)
                    } else {
                        Log.i(TAG, message)
                    }
                }
                true
            }

            WHAT_SDK_START -> {
                launcherDelay = true
                onLaunchDelay()
                true
            }

            else -> false
        }
    }

    private val mWeakReferenceHandler = WeakReferenceHandler(weightMessageCallback)
    private val mHelper = PackageHelper()

    private var mTBScaleAidlInterface: TBScaleAidlInterface? = null
    private var isConfigAppInstall = false//是否已配置安装SDK
    private var isScaleInit = false //是否初始化启动SDK
    private var isBind = false//是否已绑定服务
    private var isCircleStart = false

    private var TBSStable = false
    private var launcherDelay = false

    private val mServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            //绑定服务，回调onBind()方法
            mTBScaleAidlInterface = TBScaleAidlInterface.Stub.asInterface(service)
            loongSendEmptyMessageDelayed(WHAT_TBS_CONNECTED, 0)
            isBind = true
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            mTBScaleAidlInterface = null
            loongSendEmptyMessageDelayed(WHAT_TBS_UNCONNECTED, 0)
            isBind = false
        }
    }

    override fun onStart() {
        super.onStart()
        if (isScaleInit) {
            if (isConfigAppInstall) {
                bindService()
                if (!isCircleStart) {
                    isCircleStart = true
                    loongCircleRefresh()
                }
            } else {
                val text = getString(R.string.weight_action_uninstall)
                loongSendMessage(buildMessage(text))
            }
        }
    }

    override fun onStop() {
        super.onStop()
        actionUnbind()
    }

    protected fun bindService() {
        //绑定的时候服务端自动创建
        bindService(Intent().apply {
            setAction(ACTION)
            setPackage(PACKAGE_NAME)
        }, mServiceConnection, BIND_AUTO_CREATE)
        weightConnectStart()
    }

    private fun refreshWeightRecord() {
        try {
            if (mTBScaleAidlInterface != null) {
                val tbs = mTBScaleAidlInterface!!
                val weight: Float = tbs.getNetWeight()
                val widgetValue: String? = tbs.getNetWeightString()
                val peel: Float = tbs.getTareWeight()
                val peelValue: String? = tbs.getTareWeightString()
                val unit: Int = tbs.getUnit()
                val unitString: String? = tbs.getUnitString()
                val isStable: Boolean = tbs.isWeightStable()
                val scaleId: String? = tbs.getScaleID()
                val eventBatteryPower: EventBatteryPower? = tbs.getBatteryPower()

                val mWeight = WeightEntity().apply {
                    netWeight = weight
                    netWeightString = widgetValue
                    tareWeight = peel
                    tareWeightString = peelValue
                    batteryPower = eventBatteryPower
                    setUnit(unit)
                    setUnitString(unitString)
                    setStable(isStable)
                }
                onWeightRefresh(mWeight, scaleId)
                TBSStable = true
            } else {
                setTbsUnStable()
            }
        } catch (e: RemoteException) {
            setTbsUnStable()
        }
        loongSendEmptyMessageDelayed(WHAT_REFRESH_UI, RESET_REFRESH_DELAY)
    }

    private fun setTbsUnStable() {
        if (TBSStable) {
            loongSendMessage(buildMessage(getString(R.string.weight_action_connect_error)))
            TBSStable = false
        }
    }

    private fun checkWeightLegal(): Boolean {
        if (mTBScaleAidlInterface == null) {
            return true
        }
        val weightText = try {
            mTBScaleAidlInterface?.getNetWeightString() ?: ""
        } catch (e: RemoteException) {
            ""
        } catch (ex: Exception) {
            ""
        }
        return TextUtils.isEmpty(weightText)
    }

    private fun actionUnbind() {
        if (isBind) {
            unbindService(mServiceConnection)
            isBind = false
        }
    }


    private fun loongSendMessage(message: Message) {
        mWeakReferenceHandler.sendMessage(message)
    }

    private fun loongCircleRefresh() {
        mWeakReferenceHandler.sendEmptyMessage(WHAT_REFRESH_UI)
    }

    private fun loongSendEmptyMessageDelayed(what: Int, delayMillis: Long) {
        mWeakReferenceHandler.sendEmptyMessageDelayed(what, delayMillis)
    }

    override fun onDestroy() {
        super.onDestroy()
        mWeakReferenceHandler.removeCallbacksAndMessages(null)
    }

    fun resetZero() {
        if (mTBScaleAidlInterface == null) {
            return
        }
        try {
            val zeroSuccess = mTBScaleAidlInterface?.setZero() ?: false
            if (!zeroSuccess) {
                loongSendMessage(buildMessage("请在重量稳定后归零"))
            }
        } catch (e: RemoteException) {
            e.printStackTrace()
        }
    }

    fun actionTare() {
        try {
            if (mTBScaleAidlInterface == null) {
                return
            }
            val tareSuccess = mTBScaleAidlInterface?.setTare() ?: false
            if (!tareSuccess) {
                loongSendMessage(buildMessage("请在重量稳定后去皮"))
            }
        } catch (e: RemoteException) {
            e.printStackTrace()
        }
    }


    fun startScale() {
        isScaleInit = true
        if (mHelper.checkPackInfo(PACKAGE_NAME, this)) {
            isConfigAppInstall = true

            val isRunning = mHelper.isAppBackground(PACKAGE_NAME, this)
            Log.i(TAG, "startScale: isRunning=$isRunning")
            if (!isRunning) {
                val intent = packageManager.getLaunchIntentForPackage(PACKAGE_NAME)
                if (intent != null) {
                    //putExtra传递本包名，可以让sdk在开机零点获取完成后自动跳转会来
                    intent.putExtra("PackageName", this.packageName)
                    startActivity(intent)
                    mWeakReferenceHandler.sendEmptyMessageDelayed(WHAT_SDK_START, 1500)
                } else {
                    Log.e(TAG, "start error")
                    onLaunchError()
                }
            }
        }
    }

    open fun weightConnectStart() {

    }

    open fun onLaunchError() {

    }

    open fun onLaunchDelay() {

    }

    abstract fun handleMessageImmediate(message: String)

    abstract fun handleWeightConnected()

    abstract fun handleWeightDisconnected()

    open fun onWeightError() {
        actionUnbind()
        loongSendEmptyMessageDelayed(WHAT_TBS_UNCONNECTED, 0)
        loongSendEmptyMessageDelayed(WHAT_REBIND_SERVICE, 3000)
    }

    abstract fun onWeightRefresh(entity: WeightEntity, scaleId: String?)

    fun buildMessage(message: String): Message {
        return Message.obtain().apply {
            what = WHAT_TOAST
            obj = message
        }
    }

    companion object {
        private const val TAG = "WeightAC"

        private const val PACKAGE_NAME = "com.tbossgroup.tbscale.aidl"
        private const val ACTION = "com.tbossgroup.tbscale.OTScaleService"

        private const val WHAT_SDK_START = 1000
        private const val WHAT_REFRESH_UI = 2000
        private const val WHAT_REBIND_SERVICE: Int = 2003
        private const val WHAT_TBS_CONNECTED = 2001
        private const val WHAT_TBS_UNCONNECTED = 2002
        private const val WHAT_TOAST: Int = 10000

        private const val RESET_REFRESH_DELAY = 160L
    }
}
